﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MetaData;
using System.Drawing;
using Common;
using System.Threading;

namespace DotNetCSharp
{
    public partial class AgentType
    {
        const int PotNumberWidth = 6,BetNumberWidth = 6;
        Random rand = new Random();
        Point foldButtonLocation, checkButtonLocation, callButtonLocation, raiseButtonLocation;
        MetaDataBag DataBag;
        AppWindow table;
        Bitmap currentFrame;
        FrameData currentData,lastData;
        internal List<HandData> LastHands {get; private set;}
        internal List<HandData> AllHands { get; private set; }
        HandData handData = new HandData();
        FuxiType Fuxi;


        public AgentType(FuxiType fuxi,AppWindow window)
        {
            this.Fuxi = fuxi;
            DataBag = MetaDataBag.Load();
            table = window;
            table.BringWindowToFront();
            table.Restore(new Rectangle(table.Rect.X, table.Rect.Y,
                table.Rect.X + DataBag.TableSize.Width - 1,
                table.Rect.Y + DataBag.TableSize.Height - 1));
            currentData = new FrameData();
            lastData = new FrameData();
            LastHands = new List<HandData>();
            AllHands = new List<HandData>();
        }
        public void Start()
        {
            for (; ; )
            {
                try
                {
                    lastData = currentData;
                    currentData = new FrameData();
                    currentFrame = Utility.CaptureWindow(table);
                    PopulateBasicFrameData();
                    if (currentData.NewHand)
                    {
                        if (handData != null)
                        {
                            AllHands.Add(handData);
                            if (LastHands.Count == G.Window)
                            {
                                LastHands.RemoveAt(0); 
                            }
                            LastHands.Add(handData);
                        }
                        Fuxi.NewHand();
                        handData = new HandData();
                        handData.HavePosition = currentData.LeftDealer;
                    }
                    if (currentData.CanFold == true && !string.IsNullOrEmpty(currentData.Pocket))
                    {
                        PopulateFullFrameData();
                        Fuxi.MakeDecision(currentData, handData);
                    }
                    currentFrame.Dispose();
                    Thread.Sleep(500);
                }
                catch (Exception ex)
                {
                    System.IO.StreamWriter file = new System.IO.StreamWriter("C:\\Users\\Daguang\\Documents\\log.txt",true);
                    file.WriteLine(ex.Message);
                    file.Close();
                    currentData = new FrameData();
                    lastData = new FrameData();
                    continue;
                }
            }
        }
        void PopulateBasicFrameData()
        {
            currentData.Board = GetBoard();
            currentData.Pocket = GetPocket();
            currentData.LeftDealer = GetLeftDealer();
            currentData.NewHand = (currentData.LeftDealer != lastData.LeftDealer);
            bool firstButton = GetFirstButtonState();
            bool secondButton = GetSecondButtonState();
            bool thirdButton = GetThirdButtonState();
            currentData.MyBet = GetMyBet();
            currentData.OpponentBet = GetOpponentBet();
            if(firstButton)
            {
                currentData.CanFold = true;
                foldButtonLocation = new Point(DataBag.FoldButtonRect.X, DataBag.FoldButtonRect.Y);
            }
            if (secondButton)
            {
                if (currentData.MyBet == currentData.OpponentBet)
                {
                    currentData.CanCheck = true;
                    checkButtonLocation = DataBag.SecondButtonLocation;
                }
                else
                {
                    currentData.CanCall = true;
                    callButtonLocation = DataBag.SecondButtonLocation;
                }
            }
            if (thirdButton)
            {
                if (secondButton)
                {
                    currentData.CanRaise = true;
                    raiseButtonLocation = DataBag.ThirdButtonLocation;
                }
                else
                {
                    currentData.CanCall = true;
                    callButtonLocation = DataBag.ThirdButtonLocation;
                }
            }
        }
        bool GetNewHand()
        {
            return String.IsNullOrEmpty(lastData.Pocket) && !String.IsNullOrEmpty(currentData.Pocket);
        }
        void PopulateFullFrameData()
        {
            currentData.BigBlind = GetBigBlind();
            currentData.Pot = GetPot();
            PopulateCalculatedData();
        }
        private void PopulateCalculatedData()
        {
            if (currentData.Board.Length == 0)
            {
                currentData.Round = G.Preflop;
            }
            else
            {
                currentData.Round = (currentData.Board.Length - 4) / 2;
            }
            if (currentData.Round > handData.LastRound)
            {
                handData.LastRound = currentData.Round;
            }
            if (currentData.OpponentBet > currentData.MyBet)
            {
                if (currentData.Round == G.Preflop)
                {
                    if (currentData.OpponentBet > currentData.BigBlind)
                    {
                        handData.NumOppRaisedPreflop++;
                    }
                }
                else if (currentData.Round == G.Flop)
                {
                    handData.NumOppRaisedFlop++;
                }
                else if (currentData.Round == G.Turn)
                {
                    handData.NumOppRaisedTurn++;
                }
                else if (currentData.Round == G.River)
                {
                    handData.NumOppRaisedRiver++;
                }
            }
        }
        bool GetLeftDealer()
        {
            int hash = currentFrame.GetPixel(DataBag.LeftDealerLocation.X,DataBag.LeftDealerLocation.Y).ToArgb();
            return hash == DataBag.LeftDealerHash;
        }
        int GetBigBlind()
        {
            int delimitor = table.Title.IndexOf("/");
            string s = table.Title.Substring(delimitor+1);
            s.Trim();
            delimitor = s.IndexOf(" ");
            s = s.Substring(0, delimitor);
            if (s[0] == '$')
            {
                s = s.Substring(1);
            }
            return Int32.Parse(s)/2;
        }
        string GetBoard()
        {
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < 5; i++)
            {
                int hash = Utility.GetRegionHash(currentFrame,new Rectangle(DataBag.CommonCards[i], DataBag.CardSize));
                if (DataBag.CardHashes.ContainsKey(hash))
                {
                    sb.Append(DataBag.CardHashes[hash]);
                }    
            }
            return sb.ToString();
        }
        string GetPocket()
        {
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < 2; i++)
            {
                int hash = Utility.GetRegionHash(currentFrame, new Rectangle(DataBag.MyCards[i], DataBag.CardSize));
                if (DataBag.CardHashes.ContainsKey(hash))
                {
                    sb.Append(DataBag.CardHashes[hash]);
                }
            }
            return sb.ToString();
        }
        int GetPot()
        {
            StringBuilder sb = new StringBuilder();
            int x = DataBag.PotRect.X;
            while (x < DataBag.PotRect.X + DataBag.PotRect.Width-PotNumberWidth)
            {
                int hash = Utility.GetFrontHash(currentFrame, new Rectangle(x, DataBag.PotRect.Y, PotNumberWidth, DataBag.PotRect.Height), DataBag.PotFontColor);
                if (DataBag.PotNumberHashes.ContainsKey(hash))
                {
                    sb.Append(DataBag.PotNumberHashes[hash]);
                    x += PotNumberWidth;
                }
                else
                {
                    x++;
                }
            }
            if (sb.Length != 0)
                return Int32.Parse(sb.ToString());
            else
                return 0;
        }
        int GetMyBet()
        {
            StringBuilder sb = new StringBuilder();
            int x = DataBag.MyBetRect.X;
            while (x < DataBag.MyBetRect.X + DataBag.MyBetRect.Width - BetNumberWidth)
            {
                int hash = Utility.GetFrontHash(currentFrame, new Rectangle(x, DataBag.MyBetRect.Y, BetNumberWidth, DataBag.MyBetRect.Height), DataBag.BetFontColor);
                if (DataBag.BetNumberHashes.ContainsKey(hash))
                {
                    sb.Append(DataBag.BetNumberHashes[hash]);
                    x += BetNumberWidth;
                }
                else
                {
                    x++;
                }
            }
            if (sb.Length != 0)
                return Int32.Parse(sb.ToString());
            else
                return 0;
        }
        int GetOpponentBet()
        {
            StringBuilder sb = new StringBuilder();
            int x = DataBag.OpponentBetRect.X;
            while (x < DataBag.OpponentBetRect.X + DataBag.OpponentBetRect.Width - BetNumberWidth)
            {
                int hash = Utility.GetFrontHash(currentFrame, new Rectangle(x, DataBag.OpponentBetRect.Y, BetNumberWidth, DataBag.OpponentBetRect.Height), DataBag.BetFontColor);
                if (DataBag.BetNumberHashes.ContainsKey(hash))
                {
                    sb.Append(DataBag.BetNumberHashes[hash]);
                    x += BetNumberWidth;
                }
                else
                {
                    x++;
                }
            }
            if (sb.Length != 0)
                return Int32.Parse(sb.ToString());
            else
                return 0;
        }
        bool GetFirstButtonState()
        {
            int hash = Utility.GetRegionHash(currentFrame, DataBag.FoldButtonRect);
            return hash == DataBag.FirstButtonHash;
        }
        bool GetSecondButtonState()
        {
            int hash = currentFrame.GetPixel(DataBag.SecondButtonLocation.X, DataBag.SecondButtonLocation.Y).ToArgb();
            return hash == DataBag.SecondButtonHash;
        }
        bool GetThirdButtonState()
        {
            int hash = currentFrame.GetPixel(DataBag.ThirdButtonLocation.X, DataBag.ThirdButtonLocation.Y).ToArgb();
            return hash == DataBag.ThirdButtonHash;
        }
    }
}
